package com.github.ecbp.user.service.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.ecbp.common.constant.CacheKeyConstant;
import com.github.ecbp.common.redis.RedisUtil;
import com.github.ecbp.common.resp.NameVo;
import com.github.ecbp.common.security.config.ControllerMethodScanner;
import com.github.ecbp.common.security.vo.UrlResource;
import com.github.ecbp.user.service.config.AdminSecurityConfig;
import com.github.ecbp.user.service.dto.ResourceDto;
import com.github.ecbp.user.service.service.PermissionService;
import com.github.ecbp.user.service.service.ResourceService;
import com.github.ecbp.user.service.service.RoleService;
import com.xxl.job.core.log.XxlJobLogger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@DependsOn("SpringContextUtils")
@Component
public class ResourceInitListener implements ApplicationListener<ContextRefreshedEvent> {
    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private PermissionService permissionService;

    @Autowired
    private ResourceService resourceService;

    @Autowired
    protected RoleService roleService;

    @Autowired
    private AdminSecurityConfig adminSecurityConfig;

    @Autowired
    private RedisUtil redisUtil;

    /**
     * (伪)定时器,扫描缓存中的未处理的(新增的)接口地址信息(资源)
     * 将其保存到resource表中
     *
     * @param
     * @return
     * @throws Exception
     */
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        executor.execute(() -> {
            Set<Long> permissionIds = new HashSet<>();
            final NameVo nameVo = permissionService.listDefault();

            for (; ; ) {
                String value = null;
                try {
                    value = redisUtil.srandmember(ControllerMethodScanner.UN_HANDLED_URL);
                    if (!StringUtils.isEmpty(value)) {
                        XxlJobLogger.log("待新增资源信息, param {}", value);
                        String[] sp = value.split(CacheKeyConstant.PATH_SEPARATOR);
                        if (sp.length == 2) {
                            ResourceDto resourceDTO = new ResourceDto();
                            resourceDTO.setProjectName(sp[0]);
                            resourceDTO.setUrl(sp[1]);
                            resourceDTO.setPermissionStatus(false);
                            resourceDTO.setPermissionId(nameVo.getId());

                            String detail = redisUtil.hget(ControllerMethodScanner.URL_DETAIL, value);
                            if (!StringUtils.isEmpty(detail)) {
                                UrlResource resource = JSON.parseObject(detail, UrlResource.class);
                                if (null != resource) {
                                    resourceDTO.setName(resource.getName());
                                    resourceDTO.setDescription(resource.getDescription());
                                }
                            }
                            if (StringUtils.isEmpty(resourceDTO.getName())) {
                                resourceDTO.setName(resourceDTO.getUrl());
                            }
                            Boolean result = resourceService.saveInfo(resourceDTO);
                            permissionIds.add(resourceDTO.getPermissionId());
                            XxlJobLogger.log("新增资源操作, param {} {}", result, JSONObject.toJSON(resourceDTO));
                        }
                        redisUtil.smove(ControllerMethodScanner.UN_HANDLED_URL, ControllerMethodScanner.HANDLED_URL, value);
                        redisUtil.hdel(ControllerMethodScanner.URL_DETAIL, value);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    value = null;
                } finally {
                    if (!CollectionUtils.isEmpty(permissionIds)) {
                        adminSecurityConfig.reloadTotalPermission();
                        permissionService.reloadUserPermission(permissionIds);
                    }

                    try {
                        if (StringUtils.isEmpty(value)) {
                            Thread.sleep(600000);
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }
}